package aor2.systembus;

import aor2.components.Element;
import aor2.components.Restorable;
import aor2.components.Signal;

public class SystemBus implements Restorable {
	// TODO Tracker?!

	private static SystemBus singleton = null;
	private Signal rdbus, wrbus, busybus, fcbus;
	private boolean frd, fwr, fbusy, ffb, fdb, fab; // flegovi da li je u stanju
													// visoke impedanse
	private Element databus, addressbus;
	private static Object sync = new Object();
	private static Object syncdone = new Object();
	
	private boolean syncflag = false;

	public static SystemBus getInstance() {
		if (null == singleton) {
			singleton = new SystemBus();
		}
		return singleton;
	}

	private SystemBus() {
		super();
		this.rdbus = new Signal(false);
		this.wrbus = new Signal(false);
		this.busybus = new Signal(false);
		this.fcbus = new Signal(false);
		this.databus = ADbus.DBus;
		this.addressbus = ADbus.ABus;
		frd = true;
		fwr = true;
		fbusy = true;
		ffb = true;
		fdb = true;
		fab = true;
	}

	public SystemBus(Signal rdbus, Signal wrbus, Signal busybus, Signal fcbus,
			Element databus, Element addressbus) {
		super();
		this.rdbus = rdbus;
		this.wrbus = wrbus;
		this.busybus = busybus;
		this.fcbus = fcbus;
		this.databus = databus;
		this.addressbus = addressbus;
	} // TODO mozda obrisati

	public boolean getRdbus() {
		return rdbus.isActive();
	}

	public void setRdbus(boolean active) {
		this.rdbus.setActive(active);
		this.frd = false;
	}

	public void setRdbusHigh() {
		this.frd = true;
	}

	public boolean getRdbusHigh() {
		return this.frd;
	}

	public boolean getWrbus() {
		return wrbus.isActive();
	}

	public void setWrbus(boolean active) {
		this.wrbus.setActive(active);
		this.fwr = false;
	}

	public void setWrbusHigh() {
		this.fwr = true;
	}

	public boolean getWrbusHigh() {
		return this.fwr;
	}

	public boolean getBusybus() {
		return busybus.isActive();
	}

	public void setBusybus(boolean active) {
		this.busybus.setActive(active);
		this.fbusy = false;
	}

	public void setBusybusHigh() {
		this.fbusy = true;
	}

	public boolean getBusybusHigh() {
		return this.fbusy;
	}

	public boolean getFcbus() {
		return fcbus.isActive();
	}

	public void setFcbus(boolean active) {
		this.fcbus.setActive(active);
		this.ffb = false;
	}

	public void setFcbusHigh() {
		this.ffb = true;
	}

	public boolean getFcbusHigh() {
		return this.ffb;
	}

	public long getDatabusState() {
		return databus.getState();
	}

	public void setDatabus(long data) {
		this.databus.setState(data);
		this.fdb = false;
	}

	public void setDatabusHigh() {
		this.fdb = true;
	}

	public boolean getDatabusHigh() {
		return this.fdb;
	}

	public long getAddressbusState() {
		return addressbus.getState();
	}

	public void setAddressbus(long data) {
		this.addressbus.setState(data);
		this.fab = false;
	}

	public void setAddressbusHigh() {
		this.fab = true;
	}

	public boolean getAdressbusHigh() {
		return this.fab;
	}

	public Object getSync() {
		return sync;
	}

	public Object getSyncDone() {
		return syncdone;
	}

	// TODO startsystem
	public void start() {
		synchronized (sync) {
			sync.notifyAll();
		}
	}

	public void done() {
		synchronized (syncdone) {
			syncdone.notifyAll();
			syncflag = true;
		}
	}
	
	public boolean getSyncFlag() {
		return syncflag;
	}
	
	public void setSyncFlag(boolean active) {
		syncflag = active;
	}

	@Override
	public void restore(String restorePoint) {
		String trim = restorePoint.replace(beginTag(), "");
		trim = trim.replace(endTag(), "");
		trim = trim.trim();
		String[] states = trim.split(" ");

		rdbus.clearHistory();
		wrbus.clearHistory();
		busybus.clearHistory();
		fcbus.clearHistory();

		rdbus = new Signal(Boolean.parseBoolean(states[0]));
		wrbus = new Signal(Boolean.parseBoolean(states[1]));
		busybus = new Signal(Boolean.parseBoolean(states[2]));
		fcbus = new Signal(Boolean.parseBoolean(states[3]));
		frd = Boolean.parseBoolean(states[4]);
		fwr = Boolean.parseBoolean(states[5]);
		fbusy = Boolean.parseBoolean(states[6]);
		ffb = Boolean.parseBoolean(states[7]);
		fdb = Boolean.parseBoolean(states[8]);
		fab = Boolean.parseBoolean(states[9]);

	}

	@Override
	public String createRestorePoint() {
		String res = beginTag() + "\n\t" + rdbus.isActive() + " "
				+ wrbus.isActive() + " " + busybus.isActive();
		res += " " + fcbus.isActive() + " " + frd + " " + fwr + " " + fbusy
				+ " " + ffb + " " + fdb + " " + fab + "\n" + endTag();
		return res;
	}

	@Override
	public String beginTag() {
		return "<SystemBus>";
	}

	@Override
	public String endTag() {
		return "</SystemBus>";
	}

	public void previousClk() {
		rdbus.previousClk();
		wrbus.previousClk();
		busybus.previousClk();
		fcbus.previousClk();
		// kako HIGH?
		frd = true;
		fwr = true;
		fbusy = true;
		ffb = true;
		fdb = true;
		fab = true;
	}
}
